package utils

import (
	"fmt"
	"io"
	"time"
)

type ArgsFunc func(args ...interface{}) (rval interface{})

// / 值监控
type IValMonitor interface {
	SetVal(catalog, key string, val interface{})
	DelVal(catalog, key string)
}

type IReleaseIntf interface {
	Release(args ...interface{}) interface{}
}

type IOperaAction interface {
	OperaAction(action int, args ...interface{}) (err error)
}

type IGetString interface {
	GetString(itype int, args ...interface{}) string
}

type IGetValue interface {
	GetValue(itype int, args ...interface{}) interface{}
}

type IASyncTaskBlock interface {
	OnGetData() interface{}
	OnDone(err error)
}

/*
请求响应
*/
type IRequestIntf interface {
	DoRequest(args ...interface{}) (resp interface{})
}

/*
*

	分布式锁
*/
type IMutexOpera interface {
	CreateMutex(id string, duration time.Duration) (rval interface{}, err error)
	MutextLock(mutex interface{}) (err error)
	MutextUnLock(mutex interface{}) (bool, error)
}

type IOnCreate interface {
	OnCreate()
}

type ISetLogType interface {
	SetLogType(typestr string)
}

type ICompareLess interface {
	CompareLess(c2 interface{}) bool
}

type ISearchVal interface {
	SearchVal(val interface{}) bool
}

type IGetBuf interface {
	GetBuf() []byte
}

type Fn_Callback func(sender interface{}, err error)

type ICallBack interface {
	CallBack(sender interface{}, err error)
}

func TryGetBuf(obj interface{}, args ...interface{}) ([]byte, bool) {
	if buf, ok := obj.([]byte); ok {
		return buf, true
	} else if str, ok := obj.(string); ok {
		return []byte(str), true
	} else if intf, ok := obj.(IGetBuf); ok {
		return intf.GetBuf(), true
	} else if intf, ok := obj.(IASyncTaskBlock); ok {
		return TryGetBuf(intf.OnGetData(), args...)
	}
	return nil, false
}

func TryCallBack(obj interface{}, sender interface{}, err error) bool {
	if intf, ok := obj.(ICallBack); ok {
		intf.CallBack(sender, err)
		return true
	}
	if intf, ok := obj.(IASyncTaskBlock); ok {
		intf.OnDone(err)
	}
	return false
}

func TrySetLogTypeStr(obj interface{}, typestr string) bool {
	if intf, ok := obj.(ISetLogType); ok {
		intf.SetLogType(typestr)
		return true
	}
	return false
}

const (
	ACTION_OPEN        int = 1
	ACTION_STOP        int = 2
	ACTION_RELEASE     int = 9
	ACTION_FILL_STATUS int = 100
)

/*
**
如果插件支持IReloadconf, 会返回true

	error obj执行Reloadconf返回的异常
*/
func TryOperaAction(obj interface{}, action int, args ...interface{}) (bool, error) {
	if intf, ok := obj.(IOperaAction); ok {
		return true, intf.OperaAction(action, args...)
	}
	return false, nil
}

func TryGetString(obj interface{}, itype int, args ...interface{}) (bool, string) {
	if intf, ok := obj.(IGetString); ok {
		return true, intf.GetString(itype, args...)
	}
	return false, ""
}

func TryGetStringEx(obj interface{}, itype int, args ...interface{}) string {
	if intf, ok := obj.(IGetString); ok {
		return intf.GetString(itype, args...)
	}
	return ""
}

func TryGetValue(obj interface{}, itype int, args ...interface{}) (bool, interface{}) {
	if intf, ok := obj.(IGetValue); ok {
		return true, intf.GetValue(itype, args...)
	}
	return false, nil
}

func TryGetValueDef(obj interface{}, itype int, def interface{}, args ...interface{}) interface{} {
	if intf, ok := obj.(IGetValue); ok {
		return intf.GetValue(itype, args...)
	}
	return def
}

func TryClose(obj interface{}) (bool, error) {
	if intf, ok := obj.(io.Closer); ok {
		return true, intf.Close()
	}
	return false, nil
}

func TryRelease(obj interface{}, args ...interface{}) (bool, interface{}) {
	if intf, ok := obj.(IReleaseIntf); ok {
		return true, intf.Release(args...)
	}
	return false, nil
}

func TryOnCreate(obj interface{}) bool {
	if intf, ok := obj.(IOnCreate); ok {
		intf.OnCreate()
		return true
	}
	return false
}

func TrySearchVal(obj interface{}, searchval interface{}, def bool) bool {
	if intf, ok := obj.(ISearchVal); ok {
		return intf.SearchVal(searchval)
	} else {
		return def
	}
}

/*
*

	true, c1 < c2
*/
func CompareLess(c1, c2 interface{}) bool {
	if intf, ok := c1.(ICompareLess); ok {
		return intf.CompareLess(c2)
	}

	if intf, ok := c2.(ICompareLess); ok {
		return !intf.CompareLess(c1)
	}

	if v1, ok := c1.(int); ok {
		v2 := int(GetInt64Value(c2, 0))
		return v1 < v2
	}

	if v1, ok := c1.(int64); ok {
		v2 := GetInt64Value(c2, 0)
		return v1 < v2
	}

	if v1, ok := c1.(float32); ok {
		v2 := float32(GetFloat64Value(c2, 0))
		return v1 < v2
	}

	if v1, ok := c1.(float64); ok {
		v2 := GetFloat64Value(c2, 0)
		return v1 < v2
	}

	return fmt.Sprintf("%v", c1) < fmt.Sprintf("%v", c2)
}
